package com.syncomponents.xml;

import java.io.Writer;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import javax.xml.transform.Source;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

import com.syncomponents.util.BaseConstant;

/**
 * xslt 工具类，xslt缓存, 及数据转换
 * 
 * @author sunkey
 * @date Jan 26, 2015
 */
public class XsltHelper {

    private final static Logger logger = LoggerFactory.getLogger(XsltHelper.class);

    private final static Map<String, Templates> templates = new ConcurrentHashMap<String, Templates>();

    /**
     * 获取转换器
     * @param xslSource
     * @return
     * @throws TransformerConfigurationException
     */
    public static Transformer getTransformer(Source xslSource) throws TransformerConfigurationException {
        String id = xslSource.getSystemId();
        if (null != id) {
            Templates temp = (Templates) templates.get(id);
            if (null != temp) {
                return temp.newTransformer();
            }
        }
        TransformerFactory factory = TransformerFactory.newInstance();
        Templates temp = factory.newTemplates(xslSource);
        if (null != id) {
            templates.put(id, temp);
            logger.info("source path:{}", id);
        }
        return temp.newTransformer();
    }

    public static void transform(Source xmlSource, Source xslSource, Writer result, Map<String, Object> paramMap)
            throws TransformerException {
        Assert.notNull(xmlSource, "xml Source is null");
        Assert.notNull(xslSource, "xslt Source is null");
        Assert.notNull(result, "Writer is null");

        Transformer transformer = getTransformer(xslSource);

        if (null != paramMap) {
            Set<String> keySet = paramMap.keySet();
            for (String key : keySet) {
                transformer.setParameter(key, paramMap.get(key));
            }
        }
        transformer.setOutputProperty("encoding", BaseConstant.ENCODE_TYPE_UTF8);
        StreamResult transformResult = new StreamResult(result);
        transformer.transform(xmlSource, transformResult);
    }
}
